package com.jarcheng.websocket.handler;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.jarcheng.common.utils.JWTUtils;

import com.jarcheng.mbg.entity.User;
import com.jarcheng.mbg.entity.User_ItemCollect;
import com.jarcheng.shiro.config.shiro.JWTToken;
import com.jarcheng.websocket.config.Event;
import com.jarcheng.websocket.payload.*;
import com.jarcheng.websocket.repository.UserChatMessageHistoryRepository;
import com.jarcheng.websocket.service.UserChatHistoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Component
@Slf4j
public class MessageEventHandler {
    @Autowired
    private SocketIOServer server;
    @Autowired
    DefaultSecurityManager defaultSecurityManager;
    @Autowired
    UserChatHistoryService chatHistoryService;
    @Autowired
    UserChatMessageHistoryRepository chatMessageHistoryRepository;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 添加connect事件，当客户端发起连接时调用
     *
     * @param client 客户端对象
     */
    @OnConnect
    public void onConnect(SocketIOClient client) {
        if (client != null) {
            String token = client.getHandshakeData().getSingleUrlParam("token");
            SecurityUtils.setSecurityManager(defaultSecurityManager);
            Subject subject = SecurityUtils.getSubject();
            subject.login(new JWTToken(token));
            User user = (User) subject.getPrincipal();
            String uuid = user.getUuid();
            String username = JWTUtils.getUsername(token);
            UUID sessionId = client.getSessionId();
            assert username != null;
            redisTemplate.opsForValue().set(username, sessionId);

            log.info("连接成功,【token】= {},【sessionId】= {}", token, sessionId);
            sendToEmail(username, uuid);

        } else {
            log.error("客户端为空");
        }
    }

    /**
     * 添加disconnect事件，客户端断开连接时调用，刷新客户端信息
     *
     * @param client 客户端对象
     */
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        if (client != null) {
            String token = client.getHandshakeData().getSingleUrlParam("token");
            // 模拟用户id 和token一致
            String username = JWTUtils.getUsername(token);

            UUID sessionId = client.getSessionId();
            assert username != null;
            redisTemplate.delete(username);
            log.info("客户端断开连接,【token】= {},【sessionId】= {}", username, sessionId);
            client.disconnect();
        } else {
            log.error("客户端为空");
        }
    }

    /**
     * 加入群聊
     *
     * @param client  客户端
     * @param request 请求
     * @param data    群聊
     */
    @OnEvent(value = Event.JOIN)
    public void onJoinEvent(SocketIOClient client, AckRequest request, JoinRequest data) {
        log.info("用户：{} 已加入群聊：{}", data.getUserId(), data.getGroupId());
        client.joinRoom(data.getGroupId());

        server.getRoomOperations(data.getGroupId()).sendEvent(Event.JOIN, data);
    }


    @OnEvent(value = Event.CHAT)
    public void onChatEvent(SocketIOClient client, AckRequest request, SingleMessageRequest data) {
        String token = client.getHandshakeData().getSingleUrlParam("token");
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();
        subject.login(new JWTToken(token));
        User user = (User) subject.getPrincipal();
        Optional<UUID> toUser = Optional.empty();
        String sessionId = (String) redisTemplate.opsForValue().get(data.getToUserName());
        if (sessionId != null) {
            toUser = Optional.of(UUID.fromString(sessionId));

        }

        UserChatHistory specificChat = chatHistoryService.findSpecificChat(data.getToUid(), data.getFromUid());
        UserChatHistory specificChat1 = chatHistoryService.findSpecificChat(data.getFromUid(), data.getToUid());
        if (specificChat == null) {
            specificChat = new UserChatHistory();
            specificChat.setMyUUID(user.getUuid());
            specificChat.setDate(data.getDate());
            specificChat.setLastMessage(data.getMessage());
            specificChat.setToUser(data.getToUid());
            specificChat.setToUserImg(data.getToUserImg());
            specificChat.setToUserName(data.getToUserName());

            specificChat1 = new UserChatHistory();
            specificChat1.setMyUUID(data.getToUid());
            specificChat1.setDate(data.getDate());
            specificChat1.setLastMessage(data.getMessage());
            specificChat1.setToUserName(user.getName());
            specificChat1.setToUser(user.getUuid());
            specificChat1.setToUserImg(user.getImg());
        } else {
            specificChat.setDate(data.getDate());
            specificChat.setLastMessage(data.getMessage());

            specificChat1.setDate(data.getDate());
            specificChat1.setLastMessage(data.getMessage());
        }


        if (toUser.isPresent()) {
            log.info("用户 {} 刚刚私信了用户 {}：{}", data.getFromUserName(), data.getToUserName(), data.getMessage());
            sendToSingle(toUser.get(), data);
            data.setChecked(true);
            chatMessageHistoryRepository.save(data);
            specificChat1.setNeedCheck(specificChat1.getNeedCheck() + 1);
            chatHistoryService.updateUserChat(specificChat1);
            chatHistoryService.updateUserChat(specificChat);
            sendToEmail(data.getToUserName(), data.getToUid());
            request.sendAckData(Dict.create().set("flag", true).set("message", "发送成功"));
        } else {
            chatMessageHistoryRepository.save(data);
            specificChat1.setNeedCheck(specificChat1.getNeedCheck() + 1);
            chatHistoryService.updateUserChat(specificChat1);
            chatHistoryService.updateUserChat(specificChat);

            sendToEmail(data.getToUserName(), data.getToUid());
            request.sendAckData(Dict.create()
                    .set("flag", false)
                    .set("message", "发送失败，对方不想理你(" + data.getToUid() + "不在线)"));
        }
    }

    @OnEvent(value = Event.GROUP)
    public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessageRequest data) {
        Collection<SocketIOClient> clients = server.getRoomOperations(data.getGroupId()).getClients();

        boolean inGroup = false;
        for (SocketIOClient socketIOClient : clients) {
            if (ObjectUtil.equal(socketIOClient.getSessionId(), client.getSessionId())) {
                inGroup = true;
                break;
            }
        }
        if (inGroup) {
            log.info("群号 {} 收到来自 {} 的群聊消息：{}", data.getGroupId(), data.getFromUid(), data.getMessage());
            sendToGroup(data);
        } else {
            request.sendAckData("请先加群！");
        }
    }

    @OnEvent(value = Event.EMAIL)
    public void onEmailEvent(SocketIOClient client, AckRequest request, UserChatHistory chatHistory) {
        chatHistory.setNeedCheck(0);
        chatHistoryService.updateUserChat(chatHistory);
        client.sendEvent(Event.EMAIL, chatHistoryService.findUserAllChat(chatHistory.getMyUUID()));
    }

    public void followNotice(String username, User user) {
        Optional<UUID> toUser;
        String sessionId = (String) redisTemplate.opsForValue().get(username);
        if (sessionId != null) {
            toUser = Optional.of(UUID.fromString(sessionId));
            server.getClient(toUser.get()).sendEvent(Event.FOLLOWER, user);

        }
    }

    public void likeNotice(String username, User_ItemCollect userItemCollect) {
        Optional<UUID> toUser;
        String sessionId = (String) redisTemplate.opsForValue().get(username);
        if (sessionId != null) {
            toUser = Optional.of(UUID.fromString(sessionId));
            server.getClient(toUser.get()).sendEvent(Event.LIKE, userItemCollect);

        }
    }

    public void sendToEmail(String username, String uuid) {
        Optional<UUID> toUser;
        String sessionId = (String) redisTemplate.opsForValue().get(username);
        if (sessionId != null) {
            toUser = Optional.of(UUID.fromString(sessionId));
            server.getClient(toUser.get()).sendEvent(Event.EMAIL, chatHistoryService.findUserAllChat(uuid));

        }
    }

    /**
     * 单聊
     */
    public void sendToSingle(UUID sessionId, SingleMessageRequest message) {
        server.getClient(sessionId).sendEvent(Event.CHAT, message);
    }

    /**
     * 广播
     */
    public void sendToBroadcast(BroadcastMessageRequest message) {
        log.info("系统紧急广播一条通知：{}", message.getMessage());
        for (String key : redisTemplate.keys("user*")) {
            UUID clientId = (UUID) redisTemplate.opsForValue().get(key);
            if (server.getClient(clientId) == null) {
                continue;
            }
            server.getClient(clientId).sendEvent(Event.BROADCAST, message);
        }
    }

    /**
     * 群聊
     */
    public void sendToGroup(GroupMessageRequest message) {
        server.getRoomOperations(message.getGroupId()).sendEvent(Event.GROUP, message);
    }

    public UserChatHistory GetNotNull(UserChatHistory userChatHistory, UserChatHistory userChatHistory1) {
        if ((userChatHistory == null) && (userChatHistory1 == null)) {
            return null;
        } else if (userChatHistory != null) return userChatHistory;
        else return userChatHistory1;
    }
}
